package system

import (
	consts2 "MoSkeleton/config/consts"
	"MoSkeleton/framework"
	"MoSkeleton/framework/core/consts"
	"MoSkeleton/framework/core/dto/request"
	"MoSkeleton/framework/core/dto/response"
	"MoSkeleton/framework/utils"
	"MoSkeleton/global"
	"MoSkeleton/services"
	"MoSkeleton/web/pogos/request/monitor"
	s1 "MoSkeleton/web/pogos/request/system"
	"MoSkeleton/web/v1/http/base"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"strings"
	"time"
)

type SysDictTypeCtrl struct {
	base.BaseCtrl
}

func (s *SysDictTypeCtrl) InitCtrl() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			c.Next()
		}()
		var operLog4GinReq *monitor.OperLog4GinReq
		utils.GinGet(c, consts.GinContext_OperLog_key, &operLog4GinReq)
		if operLog4GinReq == nil {
			framework.MoLogger.Error("未找到操作日志信息")
			return
		}
		operLog4GinReq.Title = "字典类型管理"
	}
}

// GetDataTypeList
// @Tags 字典类型
// @Summary 数据字典列表
// @Security ApiKeyAuth
// @Param data query system.SysDictTypePageReq true "数据字典参数"
// @Success 200 {object} response.Response{data=response.PageResult} "{"code": 200, "data": [...]}"
// @Router /system/dict/type/list [get]
func (d *SysDictTypeCtrl) GetDataTypeList(c *gin.Context) {
	dictTypeReq := s1.SysDictTypePageReq{}

	if err := c.ShouldBindQuery(&dictTypeReq); err != nil {
		global.MoLogger.Info("参数错误", zap.Error(err))
		response.FailMsg(c, consts.ValidatorParamsCheckFailCode, "参数错误")
		return
	}
	dictTypeReq.ShouldBindParams(c)
	pageResult, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.GetDataTypePage(&dictTypeReq)
	if err != nil {
		global.MoLogger.Info("查询数据字典列表失败", zap.Error(err))
		response.FailMsg(c, consts.CommSelectFailCode, "服务内部错误")
		return
	}
	response.Success(c, "查询成功", pageResult)
}

// 查询数据字典
// @Tags 字典类型
// @Summary 数据字典详情
// @Security ApiKeyAuth
// @Param id path string true "字典类型ID"
// @Success 200 {object} response.Response{data=system.SysDictTypeItemResp} "{"code": 200, "data": [...]}"
// @Router /system/dict/type/{id} [get]
func (d *SysDictTypeCtrl) GetDataTypeById(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		global.MoLogger.Info("参数错误")
		response.FailMsg(c, consts.ValidatorParamsCheckFailCode, "参数错误")
		return
	}
	itemResp, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.GetDataTypeById(id)
	if err != nil {
		global.MoLogger.Info("查询数据字典失败", zap.Error(err))
		response.FailMsg(c, consts.CommSelectFailCode, "服务内部错误")
		return
	}
	response.Success(c, "查询成功", itemResp)
}

// 更新数据字典
// @Tags 字典类型
// @Summary 更新数据字典
// @Security ApiKeyAuth
// @Param data body system.SysDictTypeUpdateReq true "数据字典参数"
// @Success 200 {object} response.Response{data=system.SysDictTypeItemResp} "{"code": 200, "data": [...]}"
// @Router /system/dict/type [put]
func (d *SysDictTypeCtrl) UpdateDataTypeById(c *gin.Context) {
	updateReq := s1.SysDictTypeUpdateReq{}
	if err := c.ShouldBindJSON(&updateReq); err != nil {
		global.MoLogger.Info("参数错误", zap.Error(err))
		response.FailMsg(c, consts.ValidatorParamsCheckFailCode, "参数错误")
		return
	}
	if unique, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.CheckDictTypeUnique(updateReq.DictType, updateReq.IDRequest); err != nil {
		global.MoLogger.Info("检测数据字典出错", zap.Error(err))
		response.FailMsg(c, consts.CommUpdateFailCode, "服务内部错误")
		return
	} else if !unique {
		global.MoLogger.Info("字典类型已存在")
		response.FailMsg(c, consts.CommUpdateFailCode, "字典类型已存在")
		return
	}
	updateReq.UpdatedBy = utils.GetUsernameFromGin(c)
	if ok, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.UpdateDateTypeById(&updateReq); err != nil {
		global.MoLogger.Info("更新数据字典失败", zap.Error(err))
		response.FailMsg(c, consts.CommUpdateFailCode, "服务内部错误")
		return
	} else if !ok {
		response.FailMsg(c, consts.CommUpdateFailCode, "更新失败")
		return
	}
	response.Success(c, "更新成功", nil)
}

// 新增数据字典
// @Tags 字典类型
// @Summary 新增数据字典
// @Security ApiKeyAuth
// @Param data body system.SysDictTypeAddReq true "数据字典参数"
// @Success 200 {object} response.Response{data=system.SysDictTypeItemResp} "{"code": 200, "data": [...]}"
// @Router /system/dict/type [post]
func (d *SysDictTypeCtrl) AddDataType(c *gin.Context) {
	addReq := s1.SysDictTypeAddReq{}
	if err := c.ShouldBindJSON(&addReq); err != nil {
		global.MoLogger.Info("参数错误", zap.Error(err))
		response.FailMsg(c, consts.ValidatorParamsCheckFailCode, "参数错误")
		return
	}
	if unique, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.CheckDictTypeUnique(addReq.DictType, request.IDRequest{}); err != nil {
		global.MoLogger.Info("检测数据字典出错", zap.Error(err))
		response.FailMsg(c, consts.CommUpdateFailCode, "服务内部错误")
		return
	} else if !unique {
		global.MoLogger.Info("字典类型已存在")
		response.FailMsg(c, consts.CommUpdateFailCode, "字典类型已存在")
		return
	}
	addReq.CreatedBy = utils.GetUsernameFromGin(c)
	addReq.UpdatedBy = addReq.CreatedBy
	ok, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.AddDataType(&addReq)
	if err != nil {
		global.MoLogger.Info("添加数据字典失败", zap.Error(err))
		response.FailMsg(c, consts.CommUpdateFailCode, "服务内部错误")
		return
	} else if !ok {
		response.FailMsg(c, consts.CommUpdateFailCode, "添加失败")
		return
	}
	response.Success(c, "添加成功", nil)
}

// 删除数据字典
// @Tags 字典类型
// @Summary 删除数据字典
// @Security ApiKeyAuth
// @Param id path string true "字典类型ID"
// @Success 200 {object} response.Response{data=system.SysDictTypeItemResp} "{"code": 200, "data": [...]}"
// @Router /system/dict/type/{id} [delete]
func (d *SysDictTypeCtrl) DeleteDataTypeById(c *gin.Context) {
	idStrs := strings.Split(c.Param("id"), ",")
	ids := utils.StrsToUint64s(&idStrs)
	if len(*ids) == 0 {
		global.MoLogger.Info("参数错误")
		response.FailMsg(c, consts.ValidatorParamsCheckFailCode, "参数错误")
		return
	}
	ok, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.DeleteDataTypeByIds(ids)
	if err != nil {
		global.MoLogger.Info("删除数据字典失败", zap.Error(err))
		response.FailMsg(c, consts.CommDeleteFailCode, "服务内部错误")
		return
	} else if !ok {
		response.FailMsg(c, consts.CommDeleteFailCode, "删除失败")
		return
	}
	response.Success(c, "删除成功", nil)
}

// 刷新字典缓存
// @Tags 字典类型
// @Summary 刷新字典缓存
// @Security ApiKeyAuth
// @Success 200 {object} response.Response{data=system.SysDictTypeItemResp} "{"code": 200, "data": [...]}"
// @Router /system/dict/type/refreshCache [delete]
func (d *SysDictTypeCtrl) RefreshCache(c *gin.Context) {
	if err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.RefreshCache(); err != nil {
		global.MoLogger.Info("刷新字典缓存失败", zap.Error(err))
		response.FailMsg(c, consts.CommDeleteFailCode, "刷新字典缓存失败")
		return
	}
	response.Success(c, "刷新字典缓存成功", nil)
}

// 导出数据字典
// @Tags 字典类型
// @Summary 导出数据字典
// @Security ApiKeyAuth
// @Param data body system.SysDictTypePageReq true "数据字典参数"
// @Success 200 {object} response.Response{data=system.SysDictTypeItemResp} "{"code": 200, "data": [...]}"
// @Router /system/dict/type/export [post]
func (d *SysDictTypeCtrl) ExportDataType(c *gin.Context) {
	d.IgnoreLogResponseData(c)
	dictTypeReq := s1.SysDictTypePageReq{}

	if err := c.ShouldBind(&dictTypeReq); err != nil {
		global.MoLogger.Info("参数错误", zap.Error(err))
		response.FailMsg(c, consts.ValidatorParamsCheckFailCode, "参数错误")
		return
	}
	buf, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.ExportDataType(&dictTypeReq)
	if err != nil {
		global.MoLogger.Info("导出数据字典失败", zap.Error(err))
		response.FailMsg(c, consts.ValidatorParamsCheckFailCode, "服务内部错误")
		return
	}
	response.SuccessWithFileData(c, fmt.Sprintf(consts2.Excel_Export_DictType, time.Now().Unix()), buf)
}

// 查询字典下拉列表
// @Tags 字典类型
// @Summary 查询字典下拉列表
// @Security ApiKeyAuth
// @Success 200 {object} response.Response{data=system.SysDictTypeItemResp} "{"code": 200, "data": [...]}"
// @Router /system/dict/type/optionselect [get]
func (d *SysDictTypeCtrl) OptionSelect(c *gin.Context) {
	typeItemsResp, err := services.ServiceGroupInst.SystemGroupInst.SysDictTypeServiceInst.GetDataTypeAll()
	if err != nil {
		global.MoLogger.Info("查询数据字典列表失败", zap.Error(err))
		response.FailMsg(c, consts.CommSelectFailCode, "服务内部错误")
		return
	}
	response.Success(c, "查询成功", typeItemsResp)
}
